package com.steve.summary.tcc;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: STEVE
 * @Description: 参与者具体实现（以账户服务为例）
 * @since: 2025-05-23
 */
public class AccountService implements TccParticipant {

    private static final String SERVICE_NAME = "account";   // 服务标识

    // 模拟数据库表
    private static class Account {
        String userId;  // 用户ID
        int balance;    // 余额
        int frozenAmount;   // Try阶段冻结的金额
    }

    // 存储和管理用户账户的余额和冻结金额
    private Map<String, Account> accountTable = new ConcurrentHashMap<>();
    private final TransactionLog transactionLog;    // 事务日志组件

    public AccountService(TransactionLog transactionLog) {
        this.transactionLog = transactionLog;
        // 初始化测试数据
        Account acc = new Account();
        acc.userId = "user1";
        acc.balance = 1000;
        accountTable.put("user1", acc);
    }

    /**
     * Try阶段：预留资源
     *
     * @param txId   全局事务ID
     * @param amount 操作金额
     * @return true表示预留成功
     */
    @Override
    public boolean tryExecute(String txId, int amount) {
        // 防悬挂检查
        if (transactionLog.isCancelRecordExists(txId, SERVICE_NAME)) {
            throw new IllegalStateException("存在Cancel记录，拒绝Try操作");
        }
        Account acc = accountTable.get("user1");
        synchronized (acc) {
            if (acc.balance >= amount) {
                acc.balance -= amount;
                acc.frozenAmount += amount;
                transactionLog.logTry(txId, SERVICE_NAME, "FREEZE_" + amount);
                System.out.println("[Account] Try成功，冻结金额: " + amount);
                return true;
            }
        }
        System.out.println("[Account] Try失败，余额不足");
        return false;
    }

    /**
     * Confirm阶段：确认执行
     */
    @Override
    public boolean confirm(String txId) {
        // 幂等检查
        if (transactionLog.isConfirmRecordExists(txId, SERVICE_NAME)) {
            return true;
        }
        Account acc = accountTable.get("user1");
        synchronized (acc) {
            acc.frozenAmount = 0;   // 清除冻结金额
            transactionLog.logConfirm(txId, SERVICE_NAME);
            System.out.println("[Acount] Confirm完成，实际扣款");
        }
        return true;
    }

    /**
     * Cancel阶段：补偿回滚
     */
    @Override
    public boolean cancel(String txId) {
        // 空回滚处理
        if (!transactionLog.isTryRecordExists(txId, SERVICE_NAME)) {
            transactionLog.logCancel(txId, SERVICE_NAME, true);
            System.out.println("[Account] 空回滚，无Try记录");
            return true;
        }
        // 幂等检查
        if (transactionLog.isCancelRecordExists(txId, SERVICE_NAME)) {
            System.out.println("[Account] Cancel已执行，跳过");
            return true;
        }
        Account acc = accountTable.get("user1");
        synchronized (acc) {
            String tryData = transactionLog.getTryData(txId, SERVICE_NAME);
            int amount = Integer.parseInt(tryData.split("_")[1]);
            acc.balance += amount;
            acc.frozenAmount -= amount;
            transactionLog.logCancel(txId, SERVICE_NAME, false);
            System.out.println("[Account] Cancel完成，解冻金额：" + amount);
        }
        return true;
    }

    // 查询当前余额（测试用）
    public int getCurrentBalance() {
        return accountTable.get("user1").balance;
    }

    // 查询冻结金额（测试用）
    public int getFrozenAmount() {
        return accountTable.get("user1").frozenAmount;
    }

}
